from abc import ABC, abstractmethod
from typing import Any, Dict, Optional, List, Union, Tuple, Callable
from enum import Enum
import asyncio
from ..readwrite.typedef import *
from ..utils.logger import get_logger

# 添加日志记录器
logger = get_logger("driver.core")

class CommunicationProtocol(Enum):
    """通信协议枚举"""
    SERIAL = "serial"
    OPC_UA = "opcua"
    SIEMENS_S7 = "s7"
    HTTP = "http"
    HTTPS = "https"
    WEBSOCKET = "websocket"
    SOCKET = "socket"
    MODBUS_TCP = "modbus_tcp"
    MODBUS_RTU = "modbus_rtu"
    PROFINET = "profinet"
    CANOPEN = "canopen"
    BACNET = "bacnet"
    DEVICE_NET = "devicenet"
    ETHERCAT = "ethercat"
    ETHERNET_IP = "ethernet_ip"

class ConfirmationMode(Enum):
    """确认模式枚举"""
    NONE = "none"  # 无确认
    BASIC = "basic"  # 基本确认（发送后确认）
    RETRANSMISSION = "retransmission"  # 重传确认（失败后重试）
    HANDSHAKE = "handshake"  # 握手确认（双向确认）

class CommunicationInterface(ABC):
    """通信接口基类：必须指定协议类型"""


    def __init__(self, config: Dict[str, Any] = None):
        self.config = config
        self.is_connected = False
        self.protocol = None
        self.device_id = config.get("device_id", "unknown_device")
        self.connection_callbacks: List[Callable] = []  # 连接状态变化回调函数列表
        self.data_callbacks: List[Callable] = []  # 数据接收回调函数列表
        self.default_confirmation_mode = ConfirmationMode.BASIC  # 默认确认模式

    @abstractmethod
    def connect(self) -> bool:
        """建立连接"""
        pass

    @abstractmethod
    def disconnect(self) -> bool:
        """断开连接"""
        pass

    @abstractmethod
    def is_available(self) -> bool:
        """检查连接是否可用,如果连接不可用，尝试自动重连,用于心跳诊断
        需要更新连接状态 is_connected
        """
        pass

    @abstractmethod
    def send_data(self, data: Any, **kwargs) -> Any:
        """发送数据"""
        pass

    @abstractmethod
    def receive_data(self, timeout: Optional[float] = None) -> Any:
        """
        接收数据（轮询方式，建议使用回调机制替代）

        Args:
            timeout: 超时时间

        Returns:
            Any: 接收到的数据
        """
        pass

    @abstractmethod
    def execute_command(self, command: str, params: Optional[Dict] = None) -> Any:
        """执行命令"""
        pass

    def get_config(self, key: str, default: Any = None) -> Any:
        """
        获取配置项的值

        Args:
            key: 配置项键名
            default: 默认值

        Returns:
            配置项的值或默认值
        """
        return self.config.get(key, default)

    def set_config(self, key: str, value: Any) -> None:
        """
        设置配置项的值

        Args:
            key: 配置项键名
            value: 配置项值
        """
        self.config[key] = value

    def read_batch(self, addresses: List[Union[str, int]], **kwargs) -> Dict[Union[str, int], Any]:
        """
        批量读取数据

        Args:
            addresses: 地址列表
            **kwargs: 其他参数，如超时、数据类型等

        Returns:
            Dict[Union[str, int], Any]: 地址和对应值的映射
        """
        raise NotImplementedError("批量读取功能未实现")

    def write_batch(self, data: Dict[Union[str, int], Any], **kwargs) -> bool:
        """
        批量写入数据

        Args:
            data: 地址和值的映射
            **kwargs: 其他参数，如超时、确认模式等

        Returns:
            bool: 写入是否成功
        """
        raise NotImplementedError("批量写入功能未实现")

    def read_register(self, address: Union[str, int], data_type: str = "int", **kwargs) -> Any:
        """
        读取寄存器数据

        Args:
            address: 寄存器地址
            data_type: 数据类型 (int, float, string, bool等)
            **kwargs: 其他参数，如长度、字节序等

        Returns:
            Any: 读取的数据
        """
        raise NotImplementedError("寄存器读取功能未实现")

    def write_register(self, address: Union[str, int], value: Any, data_type: str = "int", **kwargs) -> bool:
        """
        写入寄存器数据

        Args:
            address: 寄存器地址
            value: 要写入的值
            data_type: 数据类型 (int, float, string, bool等)
            **kwargs: 其他参数，如字节序等

        Returns:
            bool: 写入是否成功
        """
        raise NotImplementedError("寄存器写入功能未实现")

    def subscribe(self, address: Union[str, int], callback: Callable[[Any], None], **kwargs) -> str:
        """
        订阅数据变化

        Args:
            address: 要订阅的地址
            callback: 回调函数
            **kwargs: 其他参数，如采样频率、变化阈值等

        Returns:
            str: 订阅ID
        """
        raise NotImplementedError("订阅功能未实现")

    def unsubscribe(self, subscription_id: str) -> bool:
        """
        取消订阅

        Args:
            subscription_id: 订阅ID

        Returns:
            bool: 取消订阅是否成功
        """
        raise NotImplementedError("取消订阅功能未实现")

    async def async_send_data(self, data: Any, **kwargs) -> Any:
        """
        异步发送数据

        Args:
            data: 要发送的数据
            **kwargs: 其他参数

        Returns:
            Any: 发送操作的结果
        """
        # 默认实现为同步方法的异步包装
        return self.send_data(data, **kwargs)

    async def async_receive_data(self, timeout: Optional[float] = None) -> Any:
        """
        异步接收数据

        Args:
            timeout: 超时时间

        Returns:
            Any: 接收到的数据
        """
        # 默认实现为同步方法的异步包装
        return self.receive_data(timeout)

    def add_connection_callback(self, callback: Callable[[bool], None]) -> None:
        """
        添加连接状态变化回调函数

        Args:
            callback: 回调函数，参数为连接状态(bool)
        """
        self.connection_callbacks.append(callback)

    def add_data_callback(self, callback: Callable[[Any], None]) -> None:
        """
        添加数据接收回调函数

        Args:
            callback: 回调函数，参数为接收到的数据
        """
        self.data_callbacks.append(callback)

    def remove_data_callback(self, callback: Callable[[Any], None]) -> bool:
        """
        移除数据接收回调函数

        Args:
            callback: 要移除的回调函数

        Returns:
            bool: 是否成功移除
        """
        try:
            self.data_callbacks.remove(callback)
            return True
        except ValueError:
            return False

    def notify_data_received(self, data: Any) -> None:
        """
        通知所有数据回调函数有新数据到达
        这是内部方法，供具体实现类在接收到数据时调用

        Args:
            data: 接收到的数据
        """
        for callback in self.data_callbacks:
            try:
                callback(data)
            except Exception as e:
                # 记录回调执行错误，但不中断其他回调的执行
                logger.warning(f"数据回调执行出错: {e}")

    def get_device_info(self) -> Dict[str, Any]:
        """
        获取设备信息

        Returns:
            Dict[str, Any]: 设备信息字典
        """
        return {
            "device_id": self.device_id,
            "protocol": self.protocol.value if self.protocol else None,
            "is_connected": self.is_connected,
            "config": self.config
        }

    def diagnose(self) -> Dict[str, Any]:
        """
        诊断设备状态

        Returns:
            Dict[str, Any]: 诊断信息
        """
        raise NotImplementedError("诊断功能未实现")

    def reconnect(self, max_attempts: int = 3, delay: float = 1.0) -> bool:
        """
        重新连接设备

        Args:
            max_attempts: 最大尝试次数
            delay: 重试间隔（秒）

        Returns:
            bool: 重连是否成功
        """
        import time
        for attempt in range(max_attempts):
            try:
                self.disconnect()
                time.sleep(delay)
                if self.connect():
                    return True
            except Exception:
                if attempt == max_attempts - 1:  # 最后一次尝试
                    return False
                time.sleep(delay)
        return False

    def transaction(self, operations: List[Callable]) -> List[Any]:
        """
        执行事务操作

        Args:
            operations: 操作函数列表

        Returns:
            List[Any]: 每个操作的结果
        """
        raise NotImplementedError("事务操作功能未实现")

    def send_with_confirmation(self, data: Any, confirmation_mode: Optional[ConfirmationMode] = None,
                              max_retries: int = 3, **kwargs) -> Tuple[bool, Any]:
        """
        发送数据并等待确认

        Args:
            data: 要发送的数据
            confirmation_mode: 确认模式
            max_retries: 最大重试次数
            **kwargs: 其他参数

        Returns:
            Tuple[bool, Any]: (是否成功, 确认信息或错误信息)
        """
        # 如果未指定确认模式，则使用默认模式
        if confirmation_mode is None:
            confirmation_mode = self.default_confirmation_mode

        # 根据确认模式执行不同的确认策略
        if confirmation_mode == ConfirmationMode.NONE:
            try:
                result = self.send_data(data, **kwargs)
                return True, result
            except Exception as e:
                return False, str(e)

        elif confirmation_mode == ConfirmationMode.BASIC:
            try:
                result = self.send_data(data, **kwargs)
                # 等待确认响应
                confirmation = self.receive_data(timeout=kwargs.get('timeout', 5.0))
                return True, confirmation
            except Exception as e:
                return False, str(e)

        elif confirmation_mode == ConfirmationMode.RETRANSMISSION:
            last_error = None
            for attempt in range(max_retries):
                try:
                    result = self.send_data(data, **kwargs)
                    # 等待确认响应
                    confirmation = self.receive_data(timeout=kwargs.get('timeout', 5.0))
                    return True, confirmation
                except Exception as e:
                    last_error = str(e)
                    if attempt < max_retries - 1:  # 不是最后一次尝试
                        import time
                        time.sleep(0.1 * (attempt + 1))  # 简单的退避策略

            return False, last_error

        elif confirmation_mode == ConfirmationMode.HANDSHAKE:
            try:
                # 发送数据
                self.send_data(data, **kwargs)

                # 等待第一次确认
                ack = self.receive_data(timeout=kwargs.get('timeout', 5.0))

                # 发送确认确认
                self.send_data("ACK", **kwargs)

                # 等待最终确认
                final_confirmation = self.receive_data(timeout=kwargs.get('timeout', 5.0))

                return True, final_confirmation
            except Exception as e:
                return False, str(e)

        else:
            raise ValueError(f"不支持的确认模式: {confirmation_mode}")

    def set_confirmation_mode(self, mode: ConfirmationMode) -> None:
        """
        设置默认确认模式

        Args:
            mode: 确认模式
        """
        self.default_confirmation_mode = mode

    def wait_for_response(self, expected_response: Any = None, timeout: float = 5.0) -> Tuple[bool, Any]:
        """
        等待特定响应或超时

        Args:
            expected_response: 期望的响应（如果为None，则接受任何响应）
            timeout: 超时时间（秒）

        Returns:
            Tuple[bool, Any]: (是否收到期望响应, 实际收到的响应)
        """
        try:
            response = self.receive_data(timeout=timeout)
            if expected_response is None:
                return True, response

            # 检查是否为期望的响应
            if response == expected_response:
                return True, response
            else:
                return False, response
        except Exception as e:
            return False, str(e)

    def ping(self, data: Any = "PING", timeout: float = 3.0) -> bool:
        """
        发送ping消息并等待pong响应

        Args:
            data: ping数据
            timeout: 超时时间

        Returns:
            bool: 是否收到响应
        """
        try:
            self.send_data(data)
            response = self.receive_data(timeout=timeout)
            # 简单的ping-pong检查，实际实现可能需要根据协议调整
            return response is not None
        except Exception:
            return False


    def read(self,
             address: FullReadType,
             *args: Union[
                 int,              # timeout (seconds)
                 float,            # timeout (seconds)
                 str,              # data_type or read_option
                 DataType,         # data type enum
                 ReadOption,       # read option enum
                 PreReaderType,    # pre-read processor function
                 PostReaderType,   # post-read processor function
                 Dict[str, Any]    # additional configuration
             ],
             timeout: Optional[Union[int, float]] = None,
             data_type: Optional[Union[str, DataType]] = None,
             sync: Optional[bool] = None,
             retry: Optional[int] = None,
             raise_on_error: Optional[bool] = None,
             quality_check: Optional[bool] = None,
             prereaders: Optional[List[PreReaderType]] = None,
             postreaders: Optional[List[PostReaderType]] = None,
             batch_size: Optional[int] = None,
             **kwargs: Any) -> Union[
                 Any,                     # single read result
                 List[Any],               # batch read results as list
                 Dict[AddressType, Any],  # batch read results as dict
                 Dict[str, Any]           # config read results
             ]:
        """
        读取数据,与设备接口一致用法，此处仅做说明，不补充注释
        """
        pass


    def write(self,
              address: FullWriteType,
              value: Optional[Any] = None,
              *args: Union[
                  int,               # timeout (seconds)
                  float,             # timeout (seconds)
                  str,               # data_type or write_option
                  DataType,          # data type enum
                  WriteOption,       # write option enum
                  PreProcessorType,  # pre-write processor function
                  PostProcessorType, # post-write processor function
                  Dict[str, Any]     # additional configuration
              ],
              timeout: Optional[Union[int, float]] = None,
              data_type: Optional[Union[str, DataType, List[Union[str, DataType]]]] = None,
              sync: Optional[bool] = None,
              confirm: Optional[bool] = None,
              retry: Optional[int] = None,
              raise_on_error: Optional[bool] = None,
              quality_check: Optional[bool] = None,
              preprocessors: Optional[List[PreProcessorType]] = None,
              postprocessors: Optional[List[PostProcessorType]] = None,
              batch_size: Optional[int] = None,
              transaction: Optional[bool] = None,
              **kwargs: Any) -> Union[
                  bool,                    # single write result
                  Dict[AddressType, bool], # batch write results
                  Dict[str, Any]           # config write results
              ]:
        """
        写入数据,与设备接口一致用法，此处仅做说明，不补充注释
        """
        pass